/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */
package org.apache.asyncweb.server.filter;

import java.io.ByteArrayOutputStream;
import java.util.zip.GZIPOutputStream;

import org.apache.asyncweb.common.HttpHeaderConstants;
import org.apache.asyncweb.common.HttpRequest;
import org.apache.asyncweb.common.HttpResponse;
import org.apache.asyncweb.common.MutableHttpResponse;
import org.apache.asyncweb.server.HttpServiceContext;
import org.apache.asyncweb.server.HttpServiceFilter;
import org.apache.mina.core.buffer.IoBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An HttpServiceFilter compressing data using the gzip algorithm if the client
 * support it.
 * 
 * @author The Apache MINA Project (dev@mina.apache.org)
 */
public class GZipFilter implements HttpServiceFilter {

	private static final Logger LOG = LoggerFactory.getLogger(GZipFilter.class);

	/**
	 * Simply moves the request forward in the chain
	 */
	public void handleRequest(NextFilter next, HttpServiceContext context)
			throws Exception {
		next.invoke();
	}

	/**
	 * Compress the response content if the client support it
	 */
	public void handleResponse(NextFilter next, HttpServiceContext context)
			throws Exception {

		HttpRequest request = context.getRequest();
		HttpResponse response = context.getCommittedResponse();

		String ae = request.getHeader(HttpHeaderConstants.KEY_ACCEPT_ENCODING);
		if (ae != null && ae.indexOf(HttpHeaderConstants.GZIP) != -1
				&& response instanceof MutableHttpResponse) {
			// compress
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			GZIPOutputStream gzos = new GZIPOutputStream(baos);
			gzos.write(response.getContent().array());
			gzos.close();
			baos.close();

			// recreate an IoBuffer
			byte[] bytes = baos.toByteArray();
			IoBuffer gzipedResponse = IoBuffer.allocate(bytes.length);
			gzipedResponse.put(bytes);
			gzipedResponse.flip();
			if (LOG.isDebugEnabled())
				LOG.debug("Compress content from {} to {}", response
						.getContent().remaining(), gzipedResponse.remaining());

			// change the response content and content type
			MutableHttpResponse mutableResponse = (MutableHttpResponse) response;
			mutableResponse.setHeader(HttpHeaderConstants.KEY_CONTENT_ENCODING,
					HttpHeaderConstants.GZIP);
			mutableResponse.setContent(gzipedResponse);
			mutableResponse.normalize(request);
		}
		next.invoke();
	}

	public void start() {
	}

	public void stop() {
	}

}
